package com.gjy.encryption.symmetry;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;

/**
 * KEY_ALGORITHM:
 * PBEWITHMD5andDES,PBEWITHMD5AndTripleDES,PBEWITHMD5AndRC2,PBEWITHSHA1AndRC2
 * @author 宫静雨
 * @version 1.0
 * @since 2022-11-08 10:56:37
 */
public class PBECoder {

    private static final String KEY_ALGORITHM = "PBEWITHSHA1AndRC2";

    private static final Integer COUNT = 1024;
    private final Key key;
    private final String password;

    public PBECoder(String password) {
        Security.addProvider(new BouncyCastleProvider());
        this.password = password;
        this.key = initKey();
    }

    public byte[] encrypt(byte[] data, byte[] salt) {
        try {
            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, COUNT);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] decrypt(byte[] data, byte[] salt) {
        try {
            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, COUNT);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] salt() {
        try {
            return new SecureRandom().generateSeed(8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Key initKey() {
        try {
            PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generateSecret(pbeKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
